package com.by.basicgateway.intercept.filter;

import com.by.gatewayhelper.GatewayContext;
import com.google.common.collect.Lists;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.by.toolkit.utils.ExceptionUtil.getStackTrace;

@Slf4j
@Component
public class GatewayFilterSupport {


    private static final List<String> IGNORE_HEADERS = Lists.newArrayList(
            "corpcode",
            "corpid",
            "projectcategory",
            "projectcode",
            "projectid",
            "mpappcode"
    );

    @Resource
    private GatewayContext gatewayContext;

    public ServerWebExchange dealHeader(ServerWebExchange exchange, String changedPath, Map<String, String> headerMap, List<String> unIgnoreHeaders) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        List<String> disIgnoreHeaders = CollectionUtils.isEmpty(unIgnoreHeaders) ? Collections.emptyList() : unIgnoreHeaders;
        ServerHttpRequest newRequest = request
                .mutate()
                .path(changedPath)
                .headers(httpHeaders -> {
                    if (Objects.isNull(headerMap) || headerMap.isEmpty()) {
                        return;
                    }
                    httpHeaders.keySet()
                            .forEach(h -> {
                                if (disIgnoreHeaders.contains(h.toLowerCase())) {
                                    return;
                                }
                                if (IGNORE_HEADERS.contains(h.toLowerCase())) {
                                    httpHeaders.remove(h);
                                }
                            });
                    log.info("[GatewayFilterSupport][dealHeader] path:[{}] filteredHttpHeaders:[{}]", path, httpHeaders);
                    headerMap.forEach(httpHeaders::add);
                }).build();
        log.info("[GatewayFilterSupport][dealHeader] path:[{}] changedPath:[{}] headerMap:[{}] newRequestHeaders:[{}]", path, changedPath, headerMap, newRequest.getHeaders());
        return exchange.mutate()
                .request(newRequest)
                .build();
    }

    public ServerWebExchange dealHeader(ServerWebExchange exchange, Map<String, String> headerMap, List<String> unIgnoreHeaders) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        if (Objects.isNull(headerMap) || headerMap.isEmpty()) {
            log.info("[GatewayFilterSupport][dealHeader] path:[{}] headerMapIsEmpty", path);
            return exchange;
        }
        List<String> disIgnoreHeaders = CollectionUtils.isEmpty(unIgnoreHeaders) ? Collections.emptyList() : unIgnoreHeaders;
        ServerHttpRequest newRequest = request
                .mutate()
                .headers(httpHeaders -> {
                    httpHeaders.keySet()
                            .forEach(h -> {
                                if (disIgnoreHeaders.contains(h.toLowerCase())) {
                                    return;
                                }
                                if (IGNORE_HEADERS.contains(h.toLowerCase())) {
                                    httpHeaders.remove(h);
                                }
                            });
                    log.info("[GatewayFilterSupport][dealHeader] path:[{}] filteredHttpHeaders:[{}]", path, httpHeaders);
                    headerMap.forEach(httpHeaders::add);
                }).build();
        log.info("[GatewayFilterSupport][dealHeader] path:[{}] headerMap:[{}] newRequestHeaders:[{}]", path, headerMap, newRequest.getHeaders());
        return exchange.mutate().request(newRequest).build();
    }

    public Map<String, String> adminDomainMapInfo(String referer) {
        try {
            Map<String, String> projectInfo = gatewayContext.adminDomainMapInfo(referer);
            log.info("[GatewayFilterSupport][adminDomainMapInfo] referer:[{}] projectInfo:[{}]", referer, projectInfo);
            return projectInfo;
        } catch (Exception e) {
            log.warn("[GatewayFilterSupport][adminDomainMapInfo] hasError[{}]", getStackTrace(e));
        }
        return Collections.emptyMap();
    }

    public Map<String, String> mpDomainMapInfo(String referer) {
        try {
            Map<String, String> projectInfo = gatewayContext.mpDomainMapInfo(referer);
            log.info("[GatewayFilterSupport][mpDomainMapInfo] referer:[{}] projectInfo:[{}]", referer, projectInfo);
            return projectInfo;
        } catch (Exception e) {
            log.warn("[GatewayFilterSupport][mpDomainMapInfo] hasError[{}]", getStackTrace(e));
        }
        return Collections.emptyMap();
    }

    public Map<String, String> projectCodeMapInfo(String projectCode) {
        try {
            Map<String, String> projectInfo = gatewayContext.projectCodeMapInfo(projectCode);
            log.info("[GatewayFilterSupport][projectCodeMapInfo] projectCode:[{}] projectInfo:[{}]", projectCode, projectInfo);
            return projectInfo;
        } catch (Exception e) {
            log.warn("[GatewayFilterSupport][projectCodeMapInfo] hasError[{}]", getStackTrace(e));
        }
        return Collections.emptyMap();
    }

    public Map<String, String> projectIdMapInfo(String projectId) {
        try {
            Map<String, String> projectInfo = gatewayContext.projectIdMapInfo(projectId);
            log.info("[GatewayFilterSupport][projectIdMapInfo] projectId:[{}] projectInfo:[{}]", projectId, projectInfo);
            return projectInfo;
        } catch (Exception e) {
            log.warn("[GatewayFilterSupport][projectIdMapInfo] hasError[{}]", getStackTrace(e));
        }
        return Collections.emptyMap();
    }

    public Map<String, String> wxMaAppIdMapInfo(String wxMaAppId) {
        try {
            Map<String, String> projectInfo = gatewayContext.wxMaAppIdMapInfo(wxMaAppId);
            log.info("[GatewayFilterSupport][wxMaAppIdMapInfo] wxMaAppId:[{}] projectInfo:[{}]", wxMaAppId, projectInfo);
            return projectInfo;
        } catch (Exception e) {
            log.warn("[GatewayFilterSupport][wxMaAppIdMapInfo] hasError[{}]", getStackTrace(e));
        }
        return Collections.emptyMap();
    }

}
